import { defineStore } from 'pinia'
import useHttp from '@renderer/utils/http'
import { useLocalStorage } from '@vueuse/core'
import { store } from '../'

const CART = 'YYDJ_CART'
const SKUS = 'SKUS'
const cartStorage = useLocalStorage(CART, {
  [SKUS]: []
})
export interface Combination {
  key: string
  value: string
}
export interface SKU {
  id: number
  name: string
  price: number
  discountPrice?: number
  url?: string
  spu_id: number
  stock: number
  combination: any
  number?: number
  selected?: boolean
  warning_stock?: number
  is_default: number
  is_relate: number
}

const matchSku = (sku: SKU, skus: SKU[]): [sku | null | undefined, number] => {
  const index = skus.findIndex((s) => s.id === sku.id)
  return [skus[index], index]
}
export const useCartStore = defineStore({
  id: 'app-sgopping-cart',
  state: (): IUserState => ({
    skus: [],
    comboSkus: []
  }),
  getters: {
    getskus(state) {
      return state.skus.filter((sku) => sku.number)
    },
    getComboSkus(state) {
      return state.comboSkus.filter((sku) => sku.number)
    },
    getSelectedSkus(state) {
      return state.skus.filter((sku) => sku.selected && sku.number > 0)
    },
    getSelectedComboSkus(state) {
      return state.comboSkus.filter((sku) => sku.number > 0 && sku.selected)
    },
    totalPrice(state) {
      return (
        state.skus.reduce((prev, cur) => {
          if (cur.selected) {
            prev += Number(cur.price) * Number(cur.number)
          }
          return prev
        }, 0) + Math.ceil(state.totalComboDiscountPrice)
      )
    },
    totalSelectedPieces(state) {
      return state.getSelectedSkus.length + state.getSelectedComboSkus.length
    },
    totalPieces(state) {
      return state.getskus.length + state.getComboSkus.length
    },
    totalComboDiscountPrice(state) {
      return Number(
        state.comboSkus.reduce((prev, combo) => {
          if (combo.selected) {
            prev +=
              Number(combo.number) *
              combo.skus.reduce((total, sku) => {
                return (total += Math.ceil((Number(sku.price) * Number(sku.discount)) / 10))
              }, 0)
          }
          return prev
        }, 0)
      )
    },
    totalComboOriginPrice(state) {
      return Number(
        state.comboSkus.reduce((prev, combo) => {
          if (combo.selected) {
            prev +=
              Number(combo.number) *
              combo.skus.reduce((total, sku) => {
                return (total += Number(sku.price))
              }, 0)
          }
          return prev
        }, 0)
      )
    },
    totalDiscount(state) {
      return (
        state.skus.reduce((prev, cur) => {
          if (cur.selected && cur.number > 0 && cur.discountPrice) {
            prev += cur.number * (cur.discountPrice - cur.price)
          }
          return prev
        }, 0) +
        state.totalComboOriginPrice -
        state.totalComboDiscountPrice
      )
    },
    getSkuById(state) {
      return (skuId: number) => state.skus.find((sku) => sku.id === skuId)
    },
    allChecked(state) {
      return state.skus.every((sku) => sku.selected) && state.comboSkus.every((sku) => sku.selected)
    },
    partChecked(state) {
      return (
        !state.allChecked &&
        (state.skus.some((sku) => sku.selected) || state.comboSkus.some((sku) => sku.selected))
      )
    },
    noChecked(state) {
      return !state.allChecked && !state.partChecked
    }
  },
  actions: {
    async init() {
      const { data: res } = await useHttp('/cart/list').get().json()
      if (res?.value?.code === 200) {
        const data = res.value.data
        if (data?.skus) {
          this.skus = JSON.parse(data.skus)
        }
      }
      const { data: comboRes } = await useHttp('/cart/c/combo/list').get().json()
      if (comboRes?.value?.code === 200) {
        const data = comboRes.value.data
        if (data?.skus) {
          this.comboSkus = JSON.parse(data.skus)
        }
      }
    },
    add(sku: SKU) {
      if (!sku.number) {
        sku.number = 1
      }
      const [match] = matchSku(sku, this.skus)
      if (!match) {
        this.skus.push(sku)
      } else {
        match.number = match.number || 0 + sku.number
      }
      sku.selected = true
      this.updateRemoteSkus()
    },
    addCombo(combo: any) {
      if (!combo.number) {
        combo.number = 1
      }
      combo.skus = [...combo.skus]
      combo.skuIds = combo.skus.map((sku) => sku.id)
      const matched = this.comboSkus.find(
        (comboSku) => [...comboSku.skuIds].sort().join(',') === [...combo.skuIds].sort().join(',')
      )
      if (matched) {
        matched.selected = true
        matched.number = Number(matched.number) + Number(combo.number)
      } else {
        this.comboSkus.push(combo)
      }
      combo.selected = true
      this.updateRemoteComboSkus()
    },
    remove(skus: SKU[]) {
      skus.forEach((sku) => {
        const [match, index] = matchSku(sku, this.skus)
        if (match) {
          this.skus.splice(index, 1)
        }
      })
      this.updateRemoteSkus()
    },
    select(sku: SKU) {
      const [match] = matchSku(sku, this.skus)
      if (match && !match.selected) {
        match.selected = true
      }
    },
    unselect(sku: SKU) {
      const [match] = matchSku(sku, this.skus)
      if (match && match.selected) {
        match.selected = false
      }
      this.updateRemoteSkus()
    },
    selectAll() {
      this.skus.forEach((sku: SKU) => (sku.selected = true))
    },
    unSelectAll() {
      this.skus.forEach((sku: SKU) => (sku.selected = false))
    },
    find(id: number) {
      return this.skus.find((s) => s.id === id)
    },
    delete(sku: SKU) {
      const [match, index] = matchSku(sku, this.skus)
      if (match) {
        this.skus.splice(index, 1)
        this.updateRemoteSkus()
      }
    },
    deleteCombo(combo: any) {
      console.log(combo)
      const index = this.comboSkus.findIndex((comboSku) => comboSku.id === combo.id)
      if (index > -1) {
        this.comboSkus.splice(index, 1)
        this.updateRemoteComboSkus()
      }
    },
    clear(type?: string) {
      this.comboSkus.splice(0, this.comboSkus.length)
      this.skus.splice(0, this.skus.length)
      if (!type) {
        this.updateRemoteSkus()
        this.updateRemoteComboSkus()
      }
    },
    updateCheck(sku: SKU, v) {
      sku.selected = v
    },
    updateComboCheck(combo, v) {
      combo.selected = v
    },
    updateAllCheck(v) {
      this.skus.forEach((sku) => (sku.selected = v))
      this.comboSkus.forEach((combo) => (combo.selected = v))
    },
    deleteSelected() {
      this.skus = this.skus.filter((sku) => !sku.selected)
      this.comboSkus = this.comboSkus.filter((combo) => !combo.selected)
      this.updateRemoteSkus()
      this.updateRemoteComboSkus()
    },
    // 更新远程购物车列表
    async updateRemoteSkus() {
      const { data: res } = await useHttp('/cart/create')
        .post({ skus: this.getSelectedSkus })
        .json()
      if (res.value.code === 200) {
        // @todo
      }
    },
    // 更新远程购物车套餐列表
    async updateRemoteComboSkus() {
      const { data: res } = await useHttp('/cart/c/combo/create')
        .post({ skus: this.comboSkus })
        .json()
      if (res.value.code === 200) {
        // @todo
      }
    },
    // 服务器上拉取购物车列表
    async pullSkus() {
      const { data: res } = await useHttp('/cart/list').get().json()
      if (res.value.code === 200) {
        console.log(res.value.data)
      }
    },
    // 清除本地的购物车列表
    clearLocalSkus() {
      cartStorage.value[SKUS] = null
    },
    // 更新本地购物车列表
    updateLocalSkus(skus: SKU[]) {
      cartStorage.value[SKUS] = skus
    },
    // 清空购物车列表（本地和远程服务器）
    async clearSkus() {
      this.clearLocalSkus()
      const { data: res } = await useHttp('/cart/create')
        .post({
          skus: '[]'
        })
        .json()

      if (res.value.code === 200) {
        return true
      }
    }
  }
})

export function useCartStoreWithout() {
  return useCartStore(store)
}
